package kycadminrepo

import (
	"context"
	"sort"
	"strconv"
	"strings"

	"code.bydev.io/cht/customer/kyc_dbstructure.git/pkg/o_kyc_transfer"
	"git.bybit.com/svc/go/pkg/bdal/bqb"
)

func (r *repo) GetTarTransferRecord(ctx context.Context, memberID, curID int64, transID string) (*o_kyc_transfer.Record, error) {
	pool, err := r.userDB.DBDefaultReplicaNodePool(ctx)
	if err != nil {
		return nil, err
	}
	var (
		SQL  bqb.SQL
		args bqb.Args
	)

	if curID > 0 {
		SQL = o_kyc_transfer.Select().WhereC(func(wb *bqb.WhereBuilder) {
			wb.EQ(o_kyc_transfer.FldTarMemberId, o_kyc_transfer.FldTarMemberId.ParamPlaceholder())
			wb.LT(o_kyc_transfer.FldId, o_kyc_transfer.FldId.ParamPlaceholder())
		}).OrderByC(o_kyc_transfer.FldId, bqb.DESC).LimitC(1).SQL()
		args = bqb.Args{
			o_kyc_transfer.FldTarMemberId.Param(): memberID,
			o_kyc_transfer.FldId.Param():          curID,
		}

	} else {
		SQL = o_kyc_transfer.Select().WhereC(func(wb *bqb.WhereBuilder) {
			o_kyc_transfer.FldTarMemberId.EQ(wb)
			o_kyc_transfer.FldTransId.EQ(wb)
		}).OrderByC(o_kyc_transfer.FldId, bqb.DESC).LimitC(1).SQL()
		args = bqb.Args{
			o_kyc_transfer.FldTarMemberId.Param(): memberID,
			o_kyc_transfer.FldTransId.Param():     transID,
		}
	}

	return o_kyc_transfer.ScanRecordNil(SQL.QueryArgs(ctx, pool, args))
}

func (r *repo) GetSrcTransferRecord(ctx context.Context, memberID, curID int64, transID string) (*o_kyc_transfer.Record, error) {
	pool, err := r.userDB.DBDefaultReplicaNodePool(ctx)
	if err != nil {
		return nil, err
	}
	var (
		SQL  bqb.SQL
		args bqb.Args
	)

	if curID > 0 {
		SQL = o_kyc_transfer.Select().WhereC(func(wb *bqb.WhereBuilder) {
			wb.EQ(o_kyc_transfer.FldSrcMemberId, o_kyc_transfer.FldSrcMemberId.ParamPlaceholder())
			wb.GT(o_kyc_transfer.FldId, o_kyc_transfer.FldId.ParamPlaceholder())
		}).OrderByC(o_kyc_transfer.FldId, bqb.ASC).LimitC(1).SQL()
		args = bqb.Args{
			o_kyc_transfer.FldSrcMemberId.Param(): memberID,
			o_kyc_transfer.FldId.Param():          curID,
		}
	} else {
		SQL = o_kyc_transfer.Select().WhereC(func(wb *bqb.WhereBuilder) {
			o_kyc_transfer.FldSrcMemberId.EQ(wb)
			o_kyc_transfer.FldTransId.EQ(wb)
		}).OrderByC(o_kyc_transfer.FldId, bqb.ASC).LimitC(1).SQL()
		args = bqb.Args{
			o_kyc_transfer.FldSrcMemberId.Param(): memberID,
			o_kyc_transfer.FldTransId.Param():     transID,
		}
	}

	return o_kyc_transfer.ScanRecordNil(SQL.QueryArgs(ctx, pool, args))
}

func (r *repo) GetTarTransferIDs(ctx context.Context, memberID int64, idempotentID string) ([]string, error) {
	var (
		tarID, curID int64
		IDs          []string
	)
	tarID = memberID
	transID := idempotentID[:36]
	for {
		tarRecord, err := r.GetTarTransferRecord(ctx, tarID, curID, transID)
		if err != nil {
			return IDs, err
		}
		if tarRecord == nil {
			return IDs, nil
		}
		if len(IDs) == 0 {
			IDs = append(IDs, strconv.Itoa(int(tarRecord.TarMemberId)))
		}
		IDs = append(IDs, strconv.Itoa(int(tarRecord.SrcMemberId)))
		tarID = tarRecord.SrcMemberId
		curID = tarRecord.Id
	}
}

func (r *repo) GetSrcTransferIDs(ctx context.Context, memberID int64, idempotentID string) ([]string, error) {
	var (
		tarID, curID int64
		IDs          []string
	)
	tarID = memberID
	transID := idempotentID[:36]
	for {
		tarRecord, err := r.GetSrcTransferRecord(ctx, tarID, curID, transID)
		if err != nil {
			return IDs, err
		}
		if tarRecord == nil {
			return IDs, nil
		}
		if len(IDs) == 0 {
			IDs = append(IDs, strconv.Itoa(int(tarRecord.SrcMemberId)))
		}
		IDs = append(IDs, strconv.Itoa(int(tarRecord.TarMemberId)))
		tarID = tarRecord.TarMemberId
		curID = tarRecord.Id
	}
}

func (r *repo) GetTarTransferChain(ctx context.Context, memberID int64, idempotentID string) (string, error) {
	IDs, err := r.GetTarTransferIDs(ctx, memberID, idempotentID)
	if err != nil {
		return "", err
	}
	sort.Stable(sort.Reverse(sort.StringSlice(IDs)))
	return strings.Join(IDs, ", "), nil
}

func (r *repo) GetSrcTransferChain(ctx context.Context, memberID int64, idempotentID string) (string, error) {
	IDs, err := r.GetSrcTransferIDs(ctx, memberID, idempotentID)
	if err != nil {
		return "", err
	}
	return strings.Join(IDs, ", "), nil
}
